using System;
using System.Threading;
using Jarvis.Server.Domain;
using Jarvis.Server.Providers;
using Jarvis.Server.Workers.Messages;
using Ninject.Extensions.Logging;

namespace Jarvis.Server.Workers
{
    public class StatisticsWorker : Worker
    {
        private readonly ILogger _logger;
        private readonly IStatsProvider _statsProvider;
        private Domain.Location _lastLocation = Location.NonRecognizedLocation;

        public StatisticsWorker(ILogger logger, IStatsProvider statsProvider)
        {
            _logger = logger;
            _statsProvider = statsProvider;
            Subscribe<CurrentLocationChangedMessage>(this);
            Name = "Statistics Worker";
        }

        #region Overrides of Worker

        public override void Loop()
        {
            Thread.Yield();
        }

        #endregion

        public override void OnMessageReceived(Message message)
        {
            base.OnMessageReceived(message);

            var currentLocationChangedMessage = message as CurrentLocationChangedMessage;
            if (currentLocationChangedMessage != null)
            {
                Collect(DateTime.Now,currentLocationChangedMessage.Location);
            }
        }

        private void Collect(DateTime now, Domain.Location location)
        {
            if (!Equals(_lastLocation, location))
            {
                if(_lastLocation != Location.NonRecognizedLocation && location == Location.NonRecognizedLocation)
                {
                    _statsProvider.InsertOrUpdateLocationStats(now, _lastLocation, LocationStatsEntry.EntryKind.Exit);
                    _logger.Trace("EXIT - {0}",_lastLocation.Name);
                }
                else if (_lastLocation == Location.NonRecognizedLocation && location != Location.NonRecognizedLocation)
                {
                    _statsProvider.InsertOrUpdateLocationStats(now, location, LocationStatsEntry.EntryKind.Enter);
                    _logger.Trace("ENTER - {0}", location.Name);
                }
                else if (_lastLocation != Location.NonRecognizedLocation && location != Location.NonRecognizedLocation)
                {
                    _statsProvider.InsertOrUpdateLocationStats(now, _lastLocation, LocationStatsEntry.EntryKind.Exit);
                    _statsProvider.InsertOrUpdateLocationStats(now, location, LocationStatsEntry.EntryKind.Enter);

                    _logger.Trace("EXIT - {0}", _lastLocation.Name);
                    _logger.Trace("ENTER - {0}", location.Name);
                }
            }

            _lastLocation = location;
        }
    }
}